﻿using System;
using System.ComponentModel;
using System.Net;
using System.Threading;
using System.Threading.Tasks;

namespace RatingAuthor
{
  public static class MyWebClient
  {
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T">Result type</typeparam>
    /// <param name="address"></param>
    /// <param name="fileName"></param>
    /// <param name="result">Function that converts AsyncCompletedEventArgs into result</param>
    /// <returns></returns>
    public static Task<T> DownloadFileAsync<T>(Uri address, string fileName, Func<AsyncCompletedEventArgs, T> result)
    {
      var client = new WebClient();
      var ar = new AsyncResult<T>();
      client.DownloadFileCompleted += (s, e) => { client.Dispose(); ar.Set(result(e)); };
      client.DownloadFileAsync(address, fileName);
      return Task<T>.Factory.FromAsync(ar, ar.End);
    }

    private class AsyncResult<T> : IAsyncResult
    {
      private ManualResetEvent _event;
      private T _result;

      public AsyncResult()
      {
        _event = new ManualResetEvent(false);
      }
      public bool IsCompleted
      {
        get { return _event == null; }
      }
      public WaitHandle AsyncWaitHandle
      {
        get { return _event; }
      }
      public object AsyncState
      {
        get { return null; }
      }
      public bool CompletedSynchronously
      {
        get { return IsCompleted; }
      }
      public void Set(T e)
      {
        _result = e;
        var ev = _event;
        _event = null;
        ev.Set();
      }
      public T End(IAsyncResult arg)
      {
        return _result;
      }
    }
  }
}